<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Benchmark: escapeHTML</title>
    <script type="text/javascript" src="prototype.js"></script>
    <script type="text/javascript" src="neodom.js"></script>
    <script type="text/javascript" src="benchmark.js"></script>
    <script type="text/javascript" src="benchmark_perlish.js"></script>
    <link rel="stylesheet" href="benchmark_style.css" type="text/css" />
  </head>
  <body class="test">
    <div id="body">
      <h1>
        <a href="benchmark.html">Benchmark</a>: <var>escapeHTML</var>
        <em>faster please</em>
      </h1>
      <div id="content">
        <p>
          <button onclick="runTests(); return false;">Run tests</button>
          using 
          <input id="iterations" name="iterations" size="8" value="-1" />
          <label for="iterations">iterations</label> for each method.
          <button onclick="$$('.tester').invoke('remove'); return false">clear results</button>
        </p>
        <p>
          <label for="testString">Test String:</label>
          <input type="text" size="50" id="testString" value="5 &lt; 4 &amp;&amp; 7 &gt; &quot;seven dwarfs&quot;" />
          <button onclick="checkMethods(); return false;">check methods</button>
        </p>
      </div>
    </div>
    <script type="text/javascript">
/* <![CDATA[ */

var
  htmlString,
  OneDiv  = document.createElement('div'),
  ENTITIES = {
    '&' : '&amp;',
    '<' : '&lt;',
    '>' : '&gt;'
  };

String.escapeHTMLDiv  = document.createElement('div');
String.escapeHTMLText = document.createTextNode('');
String.escapeHTMLDiv.appendChild(String.escapeHTMLText);

Object.extend(String.prototype, {
  escapeHTML: function() {
    var div = document.createElement('div');
    var text = document.createTextNode(this);
    div.appendChild(text);
    return div.innerHTML;
  },
  escapeHTMLOneDiv: function() {
    OneDiv.innerHTML = '';
    var text = document.createTextNode(this);
    OneDiv.appendChild(text);
    return OneDiv.innerHTML;
  },
  escapeHTMLOneDiv2: function() {
    String.escapeHTMLText.data = this;
    return String.escapeHTMLDiv.innerHTML;
  },
  escapeHTMLSplit: function() {
    return this.split('&').join('&amp;')
               .split('<').join('&lt;')
               .split('>').join('&gt;');
  },
  escapeHTMLReplace: function() {
    return this.replace(/\x26/g, '&amp;')
               .replace(/\x3C/g, '&lt;')
               .replace(/\x3E/g, '&gt;');
  },
  escapeHTMLReplaceMap: function() {
    return this.replace(/[&<>]/g, function(c){return ENTITIES[c]});
  }
});

var methods = {
  'Prototype': function() {
    return this.TEST.escapeHTML()
  },
  'Prototype.oneDiv': function() {
    return this.TEST.escapeHTMLOneDiv()
  },
  'Prototype.oneDiv2': function() {
    return this.TEST.escapeHTMLOneDiv2()
  },
  'String.split': function() {
    return this.TEST.escapeHTMLSplit()
  },
  'String.replace': function() {
    return this.TEST.escapeHTMLReplace()
  },
  'String.replaceMap': function() {
    return this.TEST.escapeHTMLReplaceMap()
  }
};

function runTests() {
  new Benchmark(methods, {
    iterations: $F('iterations'),
    beforeTest: function() {
      this.TEST = this.TEST.replace(/\d*$/, this.data[this.current].iterations);
    },
    TEST: $F('testString')
  });
}

function checkMethods() {
  htmlString = $F('testString');
  var dumper = $T('pre', document.body, {className: 'tester'});
  for (methodName in methods) {
    dumper.appendChild(document.createTextNode(
      sprintf('%25s', methodName) + ': [[' +  methods[methodName].apply({TEST: htmlString}) + ']]\r\n'
    ));
  }
}
/* ]]> */
    </script>
  </body>
</html>
